from fastapi import APIRouter, Request, Depends
from pydantic import BaseModel, Field, HttpUrl
from typing import Optional, Union
from utils.logger import Logger
from utils.constants import ErrorCode, AgentType
from apps.orchestrator.async_orchestrator_agent import get_async_orchestrator
import uuid

# 初始化路由和日志
search_router = APIRouter()
logger = Logger.get_logger(agent_name="search_router")

# 定义请求模型（参数校验）
class SearchRequest(BaseModel):
    """搜索请求模型"""
    query_type: str = Field(
        ..., description="查询类型：text（文本）/doc（文档）/multi_modal（多模态）",
        enum=["text", "doc", "multi_modal"]
    )
    query: str = Field(..., description="查询关键词/问题", min_length=1, max_length=500)
    file_url: Optional[Union[HttpUrl, str]] = Field(
        None, description="文档/图片URL（仅doc/multi_modal类型需要）"
    )
    user_id: Optional[str] = Field(None, description="用户ID（可选，用于个性化推荐）")
    top_k: int = Field(default=3, description="返回结果数量", ge=1, le=10)

# 定义响应模型（格式统一）
class SearchResultItem(BaseModel):
    """单个搜索结果项"""
    content: str = Field(..., description="结果内容")
    score: float = Field(..., description="匹配分数（0-1）")
    source: str = Field(..., description="结果来源：text_qa/doc_qa/multi_modal")
    source_url: Optional[str] = Field(None, description="来源文件URL（如有）")

class SearchResponse(BaseModel):
    """搜索响应模型"""
    code: int = Field(ErrorCode.SUCCESS.value, description="错误码")
    message: str = Field("success", description="状态信息")
    data: dict = Field(..., description="结果数据")
    task_id: str = Field(..., description="任务ID（用于追踪）")
    request_id: str = Field(..., description="请求ID")

@search_router.post("/search", response_model=SearchResponse, summary="统一搜索接口")
async def search(request: Request, search_request: SearchRequest):
    """
    统一搜索接口（支持文本/文档/多模态）
    - 文本搜索：直接传入query关键词
    - 文档搜索：需传入doc类型的file_url（MinIO文件URL）
    - 多模态搜索：需传入multi_modal类型的file_url（图片/文档URL）
    """
    # 添加默认的request_id生成机制，避免依赖request.state.request_id
    request_id = getattr(getattr(request, 'state', None), 'request_id', str(uuid.uuid4()))
    logger.info(
        f"接收搜索请求: request_id={request_id}, query_type={search_request.query_type}, "
        f"query={search_request.query[:20]}..., user_id={search_request.user_id}"
    )

    try:
        # 1. 映射查询类型到Agent类型
        query_type_to_agent = {
            "text": AgentType.TEXT_QA.value,
            "doc": AgentType.DOC_QA.value,
            "multi_modal": AgentType.MULTI_MODAL.value
        }
        target_agent_type = query_type_to_agent[search_request.query_type]

        try:
            # 2. 调用异步编排器执行任务
            task_input = {
                "task_id": f"search_{request_id}",
                "task_type": "single",  # 单Agent任务
                "agent_type": target_agent_type,
                "inputs": {
                    "query": search_request.query,
                    "session_id": str(uuid.uuid4())
                },
                "query_type": search_request.query_type,
                "file_url": str(search_request.file_url) if search_request.file_url else None,
                "user_id": search_request.user_id,
                "top_k": search_request.top_k,
                "request_id": request_id
            }
            
            # 获取异步编排器实例
            orchestrator = await get_async_orchestrator()
            result = await orchestrator.execute_task_async(task_input)
            
            # 确保result是有效的字典
            response_data = {"items": []}
            
            if result.get("status") == "success":
                # 从异步编排器结果中提取答案
                final_answer = result.get("final_answer", "")
                # 将答案放入items数组，保持与原始格式兼容
                response_data["items"] = [{"content": final_answer, "score": 1.0, "source": target_agent_type}]
                # 可以添加更多元数据
                response_data["sub_task_count"] = result.get("sub_task_count", 0)
            
            logger.info(f"搜索成功: request_id={request_id}, task_id={request_id}, result_count={len(response_data.get('items', []))}")
            return {
                "code": ErrorCode.SUCCESS.value,
                "message": "success",
                "data": response_data,
                "task_id": f"search_{request_id}",
                "request_id": request_id
            }
        except Exception as e:
            # 4. 搜索失败，执行降级策略
            logger.error(f"搜索失败: request_id={request_id}, error={str(e)}", exc_info=True)
            
            # 确保降级时返回有效的数据结构
            fallback_data = {"items": [{"content": f"搜索服务暂时不可用: {str(e)}", "score": 0.0, "source": "error"}]}
            
            return {
                "code": ErrorCode.AGENT_CALL_ERROR.value,
                "message": "搜索服务暂时不可用",
                "data": fallback_data,
                "task_id": f"search_{request_id}",
                "request_id": request_id
            }
    except Exception as e:
        # 全局异常捕获，确保始终返回有效的响应格式
        logger.error(f"搜索接口异常: request_id={request_id}, error={str(e)}", exc_info=True)
        return {
            "code": ErrorCode.INTERNAL_ERROR.value,
            "message": "内部服务器错误",
            "data": {"items": []},
            "task_id": f"search_{request_id}",
            "request_id": request_id
        }